from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import TemplateView, ListView, DetailView, UpdateView, CreateView
from django.urls import reverse_lazy
from django.db.models import Count, Q
from django.utils import timezone
from datetime import timedelta
from django.core.paginator import Paginator
from django.contrib.auth.views import LoginView
from django.core.files.storage import default_storage
from django.db import transaction
from django.core.exceptions import ValidationError
from django.conf import settings
import uuid
import os

from travel.models import TravelRecord, Comment, Like
from django.contrib.auth.models import User
from .permissions import AdminPermissionMixin, is_admin_user

class AdminLoginView(LoginView):
    """管理员登录视图"""
    template_name = 'admin_panel/login.html'
    redirect_authenticated_user = True
    
    def get_success_url(self):
        return reverse_lazy('admin_panel:admin_dashboard')
    
    def form_valid(self, form):
        # 检查用户是否是管理员
        user = form.get_user()
        if not is_admin_user(user):
            from django.contrib.auth import logout
            logout(self.request)
            form.add_error(None, '您没有管理员权限')
            return self.form_invalid(form)
        return super().form_valid(form)
    
    def get(self, request, *args, **kwargs):
        if request.user.is_authenticated and is_admin_user(request.user):
            return redirect(self.get_success_url())
        return super().get(request, *args, **kwargs)

class AdminDashboardView(LoginRequiredMixin, AdminPermissionMixin, TemplateView):
    """管理仪表盘"""
    template_name = 'admin_panel/dashboard.html'
    login_url = '/admin-panel/login/'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        # 统计数据
        total_travels = TravelRecord.objects.count()
        total_users = User.objects.count()
        total_comments = Comment.objects.count()
        total_likes = Like.objects.count()
        
        # 最近7天数据
        seven_days_ago = timezone.now() - timedelta(days=7)
        recent_travels = TravelRecord.objects.filter(created_at__gte=seven_days_ago).count()
        recent_users = User.objects.filter(date_joined__gte=seven_days_ago).count()
        
        # 热门旅行地点
        popular_locations = TravelRecord.objects.exclude(location='').values('location').annotate(
            count=Count('id')
        ).order_by('-count')[:5]
        
        context.update({
            'total_travels': total_travels,
            'total_users': total_users,
            'total_comments': total_comments,
            'total_likes': total_likes,
            'recent_travels': recent_travels,
            'recent_users': recent_users,
            'popular_locations': popular_locations,
        })
        return context

class TravelRecordListView(LoginRequiredMixin, AdminPermissionMixin, ListView):
    """旅行记录列表"""
    model = TravelRecord
    template_name = 'admin_panel/travel_list.html'
    context_object_name = 'travels'
    paginate_by = 20
    ordering = ['-created_at']
    login_url = '/admin-panel/login/'
    
    def get_queryset(self):
        queryset = super().get_queryset()
        
        # 搜索功能
        search_query = self.request.GET.get('q')
        if search_query:
            queryset = queryset.filter(
                Q(title__icontains=search_query) |
                Q(description__icontains=search_query) |
                Q(location__icontains=search_query)
            )
        
        # 用户过滤
        user_id = self.request.GET.get('user')
        if user_id:
            queryset = queryset.filter(user_id=user_id)
        
        return queryset.select_related('user')
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['users'] = User.objects.all()
        context['search_query'] = self.request.GET.get('q', '')
        context['selected_user'] = self.request.GET.get('user', '')
        return context

class TravelRecordDetailView(LoginRequiredMixin, AdminPermissionMixin, DetailView):
    """旅行记录详情"""
    model = TravelRecord
    template_name = 'admin_panel/travel_detail.html'
    context_object_name = 'travel'
    login_url = '/admin-panel/login/'
    
    def get_queryset(self):
        return TravelRecord.objects.select_related('user')

class TravelRecordCreateView(LoginRequiredMixin, AdminPermissionMixin, CreateView):
    """创建旅行记录"""
    model = TravelRecord
    template_name = 'admin_panel/travel_create.html'
    fields = ['title', 'description', 'location', 'latitude', 'longitude', 'start_date', 'end_date']
    success_url = reverse_lazy('admin_panel:admin_travel_list')
    login_url = '/admin-panel/login/'
    
    @transaction.atomic
    def form_valid(self, form):
        # 设置当前用户为创建者
        form.instance.user = self.request.user
        
        # 先保存旅行记录（在事务中）
        travel_record = form.save(commit=False)
        travel_record.user = self.request.user
        
        # 处理主图索引 - 默认第一张图片为主图
        main_image_index = self.request.POST.get('main_image_index')
        if main_image_index is not None and main_image_index != '':
            try:
                travel_record.main_image_index = int(main_image_index)
            except (ValueError, TypeError):
                # 如果转换失败，设置为0（第一张图片）
                travel_record.main_image_index = 0
        else:
            # 如果没有指定主图，默认第一张图片为主图
            travel_record.main_image_index = 0
        
        travel_record.save()
        
        # 处理图片上传
        images = self.request.FILES.getlist('images')
        image_urls = []
        
        try:
            for image in images:
                # 生成唯一文件名
                file_ext = os.path.splitext(image.name)[1]
                file_name = f"{uuid.uuid4()}{file_ext}"
                file_path = f"travel_images/{file_name}"
                
                # 保存图片文件
                with default_storage.open(file_path, 'wb+') as destination:
                    for chunk in image.chunks():
                        destination.write(chunk)
                
                # 生成完整的URL（与API序列化器保持一致）
                production_host = next((host for host in settings.ALLOWED_HOSTS if host != '*'), settings.ALLOWED_HOSTS[0])
                image_url = f"https://{production_host}/media/{file_path}"
                image_urls.append(image_url)
            
            # 更新图片URL列表
            travel_record.images = image_urls
            travel_record.save()
            
        except Exception as e:
            # 如果图片上传失败，事务会自动回滚
            # 清理可能已经上传的文件
            for image_url in image_urls:
                try:
                    file_path = image_url.replace(settings.MEDIA_URL, '')
                    if default_storage.exists(file_path):
                        default_storage.delete(file_path)
                except:
                    pass
            
            form.add_error(None, f'图片上传失败: {str(e)}')
            return self.form_invalid(form)
        
        return super().form_valid(form)

class TravelRecordUpdateView(LoginRequiredMixin, AdminPermissionMixin, UpdateView):
    """旅行记录编辑"""
    model = TravelRecord
    template_name = 'admin_panel/travel_edit.html'
    fields = ['title', 'description', 'location', 'latitude', 'longitude', 'start_date', 'end_date']
    success_url = reverse_lazy('admin_panel:admin_travel_list')
    login_url = '/admin-panel/login/'
    
    @transaction.atomic
    def form_valid(self, form):
        # 保存基本信息
        travel_record = form.save()
        
        # 处理主图索引
        main_image_index = self.request.POST.get('main_image_index')
        if main_image_index is not None and main_image_index != '':
            try:
                travel_record.main_image_index = int(main_image_index)
            except (ValueError, TypeError):
                # 如果转换失败，保持原值或设置为None
                travel_record.main_image_index = None
        else:
            travel_record.main_image_index = None
        
        travel_record.save()
        
        # 处理图片管理
        retained_images = self.request.POST.getlist('retained_images')
        deleted_images = self.request.POST.getlist('deleted_images')
        new_images = self.request.FILES.getlist('new_images')
        
        # 删除标记的图片文件
        for image_url in deleted_images:
            if image_url and image_url != '':  # 确保不是空字符串
                # 检查是否是逗号分隔的字符串
                if ',' in image_url:
                    # 如果是逗号分隔的字符串，分割成数组
                    deleted_image_list = image_url.split(',')
                    for img_url in deleted_image_list:
                        if img_url and img_url != '':
                            try:
                                file_path = img_url.replace(settings.MEDIA_URL, '')
                                if default_storage.exists(file_path):
                                    default_storage.delete(file_path)
                            except Exception as e:
                                # 记录错误但继续处理
                                import logging
                                logger = logging.getLogger(__name__)
                                logger.error(f"删除图片文件失败: {file_path}, 错误: {str(e)}")
                else:
                    try:
                        file_path = image_url.replace(settings.MEDIA_URL, '')
                        if default_storage.exists(file_path):
                            default_storage.delete(file_path)
                    except Exception as e:
                        # 记录错误但继续处理
                        import logging
                        logger = logging.getLogger(__name__)
                        logger.error(f"删除图片文件失败: {file_path}, 错误: {str(e)}")
        
        # 上传新图片
        new_image_urls = []
        try:
            for image in new_images:
                # 生成唯一文件名
                file_ext = os.path.splitext(image.name)[1]
                file_name = f"{uuid.uuid4()}{file_ext}"
                file_path = f"travel_images/{file_name}"
                
                # 确保目录存在
                directory = os.path.dirname(file_path)
                if not default_storage.exists(directory):
                    # 创建目录 - 使用空字符串而不是字节
                    default_storage.save(directory + '/.keep', '')  # 创建目录

                # 保存图片文件
                with default_storage.open(file_path, 'wb+') as destination:
                    for chunk in image.chunks():
                        destination.write(chunk)
                
                # 生成完整的URL（与API序列化器保持一致）
                production_host = next((host for host in settings.ALLOWED_HOSTS if host != '*'), settings.ALLOWED_HOSTS[0])
                image_url = f"https://{production_host}/media/{file_path}"
                new_image_urls.append(image_url)
            
        except Exception as e:
            # 如果图片上传失败，清理已上传的文件
            for image_url in new_image_urls:
                try:
                    file_path = image_url.replace(settings.MEDIA_URL, '')
                    if default_storage.exists(file_path):
                        default_storage.delete(file_path)
                except:
                    pass
            form.add_error(None, f'图片上传失败: {str(e)}')
            return self.form_invalid(form)
        
        # 更新图片列表（保留的图片 + 新上传的图片）
        final_images = []
        
        # 处理保留的图片 - 修复数据格式问题
        print(f"DEBUG: retained_images = {retained_images}")
        print(f"DEBUG: deleted_images = {deleted_images}")
        print(f"DEBUG: original images = {travel_record.images if hasattr(travel_record, 'images') else 'None'}")
        
        # 处理保留的图片
        if retained_images:
            # 检查是否是逗号分隔的字符串（可能是表单提交的问题）
            if len(retained_images) == 1 and ',' in retained_images[0]:
                # 如果是逗号分隔的字符串，分割成数组
                retained_images = retained_images[0].split(',')
            
            # 检查是否是空字符串数组
            if retained_images == ['']:
                retained_images = []
            
            for img in retained_images:
                if img and img != '':  # 确保不是空字符串
                    final_images.append(img)
        else:
            # 如果没有保留图片，检查原始图片
            if hasattr(travel_record, 'images') and travel_record.images:
                final_images.extend(travel_record.images)
        
        print(f"DEBUG: final_images before new = {final_images}")
        
        final_images.extend(new_image_urls)
        
        travel_record.images = final_images
        travel_record.save()
        
        return super().form_valid(form)

class UserListView(LoginRequiredMixin, AdminPermissionMixin, ListView):
    """用户列表"""
    model = User
    template_name = 'admin_panel/user_list.html'
    context_object_name = 'users'
    paginate_by = 20
    ordering = ['-date_joined']
    login_url = '/admin-panel/login/'
    
    def get_queryset(self):
        queryset = super().get_queryset()
        
        # 搜索功能
        search_query = self.request.GET.get('q')
        if search_query:
            queryset = queryset.filter(
                Q(username__icontains=search_query) |
                Q(email__icontains=search_query) |
                Q(first_name__icontains=search_query) |
                Q(last_name__icontains=search_query)
            )
        
        return queryset.annotate(
            travel_count=Count('travelrecord'),
            comment_count=Count('comment'),
            like_count=Count('like')
        )
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['search_query'] = self.request.GET.get('q', '')
        return context

class CommentListView(LoginRequiredMixin, AdminPermissionMixin, ListView):
    """评论列表"""
    model = Comment
    template_name = 'admin_panel/comment_list.html'
    context_object_name = 'comments'
    paginate_by = 20
    ordering = ['-created_at']
    login_url = '/admin-panel/login/'
    
    def get_queryset(self):
        queryset = super().get_queryset()
        
        # 搜索功能
        search_query = self.request.GET.get('q')
        if search_query:
            queryset = queryset.filter(
                Q(content__icontains=search_query) |
                Q(user__username__icontains=search_query) |
                Q(travel_record__title__icontains=search_query)
            )
        
        return queryset.select_related('user', 'travel_record')
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['search_query'] = self.request.GET.get('q', '')
        return context

@login_required
def delete_travel_record(request, pk):
    """删除旅行记录"""
    if not is_admin_user(request.user):
        from django.core.exceptions import PermissionDenied
        raise PermissionDenied("您没有权限执行此操作")
    
    travel_record = get_object_or_404(TravelRecord, pk=pk)
    
    # 删除关联的图片文件
    if travel_record.images:
        for image_url in travel_record.images:
            try:
                # 从URL中提取文件路径
                file_path = image_url.replace(settings.MEDIA_URL, '')
                if default_storage.exists(file_path):
                    default_storage.delete(file_path)
            except Exception as e:
                # 如果文件删除失败，记录错误但继续删除记录
                import logging
                logger = logging.getLogger(__name__)
                logger.error(f"删除图片文件失败: {file_path}, 错误: {str(e)}")
    
    travel_record.delete()
    
    return redirect('admin_panel:admin_travel_list')

@login_required
def delete_comment(request, pk):
    """删除评论"""
    if not is_admin_user(request.user):
        from django.core.exceptions import PermissionDenied
        raise PermissionDenied("您没有权限执行此操作")
    
    comment = get_object_or_404(Comment, pk=pk)
    comment.delete()
    
    return redirect('admin_panel:admin_comment_list')

def admin_logout(request):
    """管理员登出"""
    from django.contrib.auth import logout
    from django.contrib import messages
    
    logout(request)
    messages.success(request, '您已成功退出登录')
    return redirect('admin_panel:admin_login')

@login_required
def bulk_delete_travel_records(request):
    """批量删除旅行记录"""
    if not is_admin_user(request.user):
        from django.core.exceptions import PermissionDenied
        raise PermissionDenied("您没有权限执行此操作")
    
    if request.method == 'POST':
        travel_ids = request.POST.getlist('travel_ids')
        
        if not travel_ids:
            from django.contrib import messages
            messages.error(request, '请选择要删除的旅行记录')
            return redirect('admin_panel:admin_travel_list')
        
        # 批量删除旅行记录
        from travel.models import TravelRecord
        from django.conf import settings
        from django.core.files.storage import default_storage
        import logging
        
        logger = logging.getLogger(__name__)
        deleted_count = 0
        
        for travel_id in travel_ids:
            try:
                travel_record = TravelRecord.objects.get(pk=travel_id)
                
                # 删除关联的图片文件
                if travel_record.images:
                    for image_url in travel_record.images:
                        try:
                            file_path = image_url.replace(settings.MEDIA_URL, '')
                            if default_storage.exists(file_path):
                                default_storage.delete(file_path)
                        except Exception as e:
                            logger.error(f"删除图片文件失败: {file_path}, 错误: {str(e)}")
                
                # 删除旅行记录
                travel_record.delete()
                deleted_count += 1
                
            except TravelRecord.DoesNotExist:
                logger.warning(f"旅行记录不存在: {travel_id}")
            except Exception as e:
                logger.error(f"删除旅行记录失败: {travel_id}, 错误: {str(e)}")
        
        from django.contrib import messages
        if deleted_count > 0:
            messages.success(request, f'成功删除 {deleted_count} 条旅行记录')
        else:
            messages.warning(request, '没有成功删除任何旅行记录')
        
        return redirect('admin_panel:admin_travel_list')
    
    return redirect('admin_panel:admin_travel_list')
